package br.requisiteworks.controller;

import java.util.Arrays;
import java.util.List;

import javax.validation.Valid;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import br.requisiteworks.modelo.Cliente;
import br.requisiteworks.modelo.service.ClienteService;
import br.requisiteworks.seguranca.modelo.UsuarioLogado;
import br.requisiteworks.util.persistencia.ErroBancoDados;
import br.requisiteworks.util.persistencia.ResultadoVazio;

/**
 * Implementacao de um controller que controla as operacoes relacionadas ao
 * modulo de {@link Cliente}s
 * 
 * @author Mikhail Domanoski
 * @version 2, 07/05/2010
 */
@Controller
@Secured("ROLE_GERENTE")
@RequestMapping("/cliente")
public class ClienteController {

	@Autowired
	private ClienteService clienteService;

	private static final Cliente VAZIO = new Cliente();

	@RequestMapping(value = "/pesquisar.do", method = RequestMethod.GET)
	public List<Cliente> pesquisar(ModelMap model) {
		try {
			return this.clienteService.listarClientes();
		} catch (ResultadoVazio e) {
			model.addAttribute("erro", e.getMessage());
			return null;
		}
	}

	@RequestMapping(value = "/pesquisar.do", method = RequestMethod.POST)
	public List<Cliente> pesquisar(@RequestParam("q") String query,
			ModelMap model) {

		if (query.matches("\\d+")) {
			try {
				return Arrays.asList(this.clienteService
						.carregarCliente(Integer.parseInt(query)));
			} catch (ResultadoVazio e) {
				model.addAttribute("erro", e.getMessage());
				return null;
			} catch (NumberFormatException e) {
				// Nao deve ocorre devido a expressao regular
				return null;
			}
		} else {
			try {
				return this.clienteService.procuraNome(query.trim());
			} catch (ResultadoVazio e) {
				model.addAttribute("erro", e.getMessage());
				return null;
			}
		}

	}

	@RequestMapping(value = "/util/pesquisar.do", method = RequestMethod.GET)
	public void pesquisar() {
	}

	@RequestMapping(value = "/util/pesquisar.do", method = RequestMethod.POST)
	public List<Cliente> pesquisarCliente(@RequestParam("q") String query,
			ModelMap model) {

		if (query.matches("\\d+")) {
			try {
				return Arrays.asList(this.clienteService
						.carregarCliente(Integer.parseInt(query)));
			} catch (ResultadoVazio e) {
				model.addAttribute("erro", e.getMessage());
				return null;
			} catch (NumberFormatException e) {
				// Nao deve ocorre devido a expressao regular
				return null;
			}
		} else {
			try {
				return this.clienteService.procuraNome(query.trim());
			} catch (ResultadoVazio e) {
				model.addAttribute("erro", e.getMessage());
				return null;
			}
		}

	}

	@RequestMapping(value = "/{numero}/detalhes.do", method = RequestMethod.GET)
	public String detalhes(@PathVariable Integer numero, ModelMap model)
			throws ResultadoVazio {
		model.addAttribute("cliente", this.clienteService
				.carregarCliente(numero));
		return "cliente/detalhes";
	}

	@RequestMapping(value = "/atualizar.do", method = RequestMethod.POST)
	public String atualizar(@Valid Cliente novoCliente, BindingResult result,
			ModelMap model) {

		if (result.hasErrors()) {
			return null;
		}

		try {
			Cliente cliente = this.clienteService.carregarCliente(novoCliente
					.getNumero());

			cliente.setNomeFantasia(novoCliente.getNomeFantasia());
			cliente.setRazaoSocial(novoCliente.getRazaoSocial());
			cliente.setUsuarioRegistro(UsuarioLogado.getUsername());

			this.clienteService.atualizarCliente(cliente);
		} catch (ErroBancoDados e) {
			model.addAttribute("erro", e.getMessage());
		}

		return "redirect:pesquisar.do";
	}

	@RequestMapping(value = "/deletar.do", method = RequestMethod.GET)
	public String deletar(@RequestParam("numero") Integer numero, ModelMap model) {
		try {
			Cliente cliente = this.clienteService.carregarCliente(numero);

			this.clienteService.deletaCliente(cliente);
		} catch (ErroBancoDados e) {
			model.addAttribute("erro", e.getMessage());
		}

		return "redirect:pesquisar.do";
	}

	@RequestMapping(value = "/adicionar.do", method = RequestMethod.GET)
	public Cliente adicionar() {
		return VAZIO;
	}

	@RequestMapping(value = "/adicionar.do", method = RequestMethod.POST)
	public String adicionar(@Valid Cliente cliente, BindingResult result,
			ModelMap model) {
		if (result.hasErrors()) {
			return null;
		}

		cliente.setUsuarioRegistro(UsuarioLogado.getUsername());

		try {
			this.clienteService.salvarCliente(cliente);
		} catch (ErroBancoDados e) {
			model.addAttribute("erro", e.getMessage());
			return null;
		}

		return "redirect:pesquisar.do";
	}

	@RequestMapping(value = "/relatorioCliente.do", method = RequestMethod.GET)
	public String gerarRelatorio() {
		return "relatorioclientes";
	}
}
